package ignite.config;

import com.mysql.cj.jdbc.MysqlDataSource;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.Ignition;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.QueryEntity;
import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory;
import org.apache.ignite.cache.store.jdbc.JdbcType;
import org.apache.ignite.cache.store.jdbc.JdbcTypeField;
import org.apache.ignite.cache.store.jdbc.dialect.MySQLDialect;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.DataStorageConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.ignite.entity.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.cache.configuration.Factory;
import javax.sql.DataSource;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Set;

@Configuration
public class IgniteConfig {
    @Resource
    private Ignite ignite;
    @PostConstruct
    void init(){
        // Load data from person table into PersonCache.
//        IgniteCache<Integer, Person> personCache = ignite.cache("PersonCache");
        IgniteCache<Object, Object> personCache = ignite.cache("person");
//        System.out.println(igniteCache);
        personCache.loadCache(null);
        System.out.println(personCache.get(1));
//        personCache.put(1,new Person(1,"1","1"));
    }
    @Bean
    public Ignite igniteInstance() {
        IgniteConfiguration cfg = new IgniteConfiguration();
//        cfg.setClientMode(true);
        cfg.setPeerClassLoadingEnabled(true);

//        TcpDiscoverySpi tcpDiscoverySpi = new TcpDiscoverySpi();
//        tcpDiscoverySpi.setLocalPort(48500);
//        tcpDiscoverySpi.setLocalPortRange(20);
//        TcpDiscoveryVmIpFinder firstIpFinder = new TcpDiscoveryVmIpFinder();
//        firstIpFinder.setAddresses(Collections.singletonList("192.168.0.128:48500..48520"));
//        TcpCommunicationSpi firstCommSpi = new TcpCommunicationSpi();
//        firstCommSpi.setLocalPort(48101);
//        tcpDiscoverySpi.setIpFinder(firstIpFinder);
//        cfg.setDiscoverySpi(tcpDiscoverySpi);
//        cfg.setCommunicationSpi(firstCommSpi);
        CacheConfiguration<Integer, Person> personCacheCfg = new CacheConfiguration<>();

        personCacheCfg.setName("person");
        personCacheCfg.setCacheMode(CacheMode.PARTITIONED);
        personCacheCfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);

        personCacheCfg.setReadThrough(true);
        personCacheCfg.setWriteThrough(true);

        CacheJdbcPojoStoreFactory<Integer, Person> factory = new CacheJdbcPojoStoreFactory<>();
        factory.setDialect(new MySQLDialect());
        factory.setDataSourceFactory((Factory<DataSource>)() -> {
            //?autoReconnect=true&useSSL=false&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
            MysqlDataSource mysqlDataSrc = new MysqlDataSource();
            mysqlDataSrc.setURL("jdbc:mysql://localhost:3306/ignite?autoReconnect=true&useSSL=false&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai");
            mysqlDataSrc.setUser("root");
            mysqlDataSrc.setPassword("root");
            return mysqlDataSrc;
        });

        JdbcType personType = new JdbcType();
        personType.setCacheName("person");
        personType.setKeyType(Integer.class);
        personType.setValueType(Person.class);
// Specify the schema if applicable
// personType.setDatabaseSchema("MY_DB_SCHEMA");
        personType.setDatabaseTable("person");

        personType.setKeyFields(
                new JdbcTypeField(java.sql.Types.INTEGER, "id", Integer.class, "id")
        );

        personType.setValueFields(
                new JdbcTypeField(java.sql.Types.INTEGER, "id", Integer.class, "id"),
                new JdbcTypeField(java.sql.Types.VARCHAR, "firstName", String.class, "firstName"),
                new JdbcTypeField(java.sql.Types.VARCHAR, "phone", String.class, "phone")
        );

        factory.setTypes(personType);

        personCacheCfg.setCacheStoreFactory(factory);

        QueryEntity qryEntity = new QueryEntity();

        qryEntity.setKeyType(Integer.class.getName());
        qryEntity.setValueType(Person.class.getName());
        qryEntity.setKeyFieldName("id");

        Set<String> keyFields = new HashSet<>();
        keyFields.add("id");
        qryEntity.setKeyFields(keyFields);

        LinkedHashMap<String, String> fields = new LinkedHashMap<>();
        fields.put("id", "java.lang.Integer");
        fields.put("firstName", "java.lang.String");
        fields.put("phone", "java.lang.String");

        qryEntity.setFields(fields);

        personCacheCfg.setQueryEntities(Collections.singletonList(qryEntity));

        cfg.setCacheConfiguration(personCacheCfg);

//        DataStorageConfiguration storageCfg = new DataStorageConfiguration();
//        storageCfg.getDefaultDataRegionConfiguration().setPersistenceEnabled(true);
//        cfg.setDataStorageConfiguration(storageCfg);

        Ignite ignite = Ignition.start(cfg);
        ignite.active(true);
        return ignite;
    }
}